package org.easy.core.util;


import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class ClassUtil {
    public static boolean isJavaClass(Class<?> clz) {
        return clz != null && clz.getClassLoader() == null;
    }

    public static boolean isBaseDataType(Class clazz) {
        return clazz.isPrimitive() ||
                clazz.equals(String.class) ||
                clazz.equals(Date.class) ||
                clazz.equals(LocalDateTime.class) ||
                clazz.equals(Boolean.class) ||
                clazz.equals(Integer.class) ||
                clazz.equals(Long.class) ||
                clazz.equals(Double.class) ||
                clazz.equals(BigDecimal.class) ||
                clazz.equals(Float.class) ||
                clazz.equals(Short.class) ||
                clazz.equals(BigInteger.class) ||
                clazz.equals(Character.class) ||
                clazz.equals(Byte.class);
    }

    public static Type[] getParameterizedTypes(Class<?> clazz) {
        Type superclassType = clazz.getGenericSuperclass();
        return !ParameterizedType.class.isAssignableFrom(superclassType.getClass()) ? null : ((ParameterizedType) superclassType).getActualTypeArguments();
    }

    public static Type[] getParameterizedTypes(Field field) {
        Type genericType = field.getGenericType();
        if (!(genericType instanceof ParameterizedType))
            return null;
        ParameterizedType pt = (ParameterizedType) genericType;
        Type[] types = pt.getActualTypeArguments();
        for (Type type : types) {
            if (type instanceof TypeVariable) {
                return null;
            }
        }
        return pt.getActualTypeArguments();
    }

    public static Type[] getParameterizedTypes(Object object) {
        return getParameterizedTypes(object.getClass());
    }

    /**
     * 获得对应类型的默认数据
     *
     * @param clazz
     * @return
     */
    public static Object getTypeDefaultData(Class<?> clazz) {
        if (clazz.equals(String.class)) {
            return clazz.getSimpleName();
        }
        if (clazz.equals(Date.class)) {
            return new Date();
        }
        if (clazz.equals(LocalDateTime.class)) {
            return LocalDateTime.now();
        }
        if (clazz.equals(Boolean.class) || clazz.equals(boolean.class)) {
            return false;
        }
        if (clazz.equals(Integer.class) || clazz.equals(int.class)) {
            return 1;
        }
        if (clazz.equals(Long.class) || clazz.equals(long.class)) {
            return 1L;
        }
        if (clazz.equals(Double.class) || clazz.equals(double.class)) {
            return 0.00d;
        }
        if (clazz.equals(BigDecimal.class)) {
            return new BigDecimal(0.00);
        }
        if (clazz.equals(Float.class) || clazz.equals(float.class)) {
            return 0.00f;
        }
        if (clazz.equals(Short.class) || clazz.equals(short.class)) {
            return (short) 0;
        }
        if (clazz.equals(BigInteger.class)) {
            return BigInteger.ONE;
        }
        if (clazz.equals(Character.class)) {
            return 'a';
        }
        if (clazz.equals(Byte.class) || clazz.equals(byte.class)) {
            return (byte) 0;
        }
        return null;
    }

    /**
     * 首字母转小写
     *
     * @param str
     * @return
     */
    public static String getLowerCaseFirstCharacterCase(String str) {
        StringBuilder sb = new StringBuilder();
        sb.append(str);
        sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
        return sb.toString();
    }

    /**
     * 首字母转大写
     *
     * @param str
     * @return
     */
    public static String getUpperCaseFirstCharacterCase(String str) {
        StringBuilder sb = new StringBuilder();
        sb.append(str);
        sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
        return sb.toString();
    }

    /**
     * 转驼峰命名法
     *
     * @param inputString
     * @return
     */
    public static String getCamelCaseString(String inputString) {
        StringBuilder sb = new StringBuilder();

        boolean nextUpperCase = false;
        for (int i = 0; i < inputString.length(); i++) {
            char c = inputString.charAt(i);

            switch (c) {
                case '_':
                case '-':
                case '@':
                case '$':
                case '#':
                case ' ':
                case '/':
                case '&':
                    if (sb.length() > 0) {
                        nextUpperCase = true;
                    }
                    break;

                default:
                    if (nextUpperCase) {
                        sb.append(Character.toUpperCase(c));
                        nextUpperCase = false;
                    } else {
                        sb.append(Character.toLowerCase(c));
                    }
                    break;
            }
        }
        return sb.toString();
    }


    /**
     * 转成蛇形命名法
     *
     * @param inputString
     * @return
     */
    public static String getSnakeCaseString(String inputString) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < inputString.length(); i++) {
            char c = inputString.charAt(i);

            if (Character.isUpperCase(c)) {
                sb.append("_");
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(Character.toLowerCase(c));
            }
        }
        return sb.toString();
    }

    /**
     * 类型的全名
     * (包名+类名)
     *
     * @param type
     * @return
     */
    public static Object tryClassForName(String type) {
        try {
            Class<?> aClass = Class.forName(type);
            return tryNewInstance(aClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }

    }

    public static Object tryNewInstance(Class<?> aClass) {
        try {
            return aClass.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取方法中所有的对应标签
     *
     * @param method
     * @param annotationType
     * @return
     */
    public static List<Annotation> getMethodAnnotation(Method method, Class<? extends Annotation> annotationType) {
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        if (parameterAnnotations.length == 0) {
            return null;
        }

        List<Annotation> result = new ArrayList();
        for (Annotation[] parameterAnnotation : parameterAnnotations) {
            for (Annotation annotation : parameterAnnotation) {
                if (annotation.annotationType() == annotationType) {
                    result.add(annotation);
                }
            }
        }
        return result;
    }


}
